#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/types.h>
#include <stdlib.h>
#include "base.h"

#define LISTEN_QUEUE_NUM 50
#define CLIENT_FP_NUM 10

void handleConn(void *arg);

int main() {

	struct sockaddr_in serverAddr, clientAddr;
	int listenFD;
	int clientFD[CLIENT_FP_NUM], cfdFlag[CLIENT_FP_NUM];
	int sockNum;
	char line[128];

	int ret;
	pthread_t ptchild;
	pthread_attr_t attr;
	pthread_mutexattr_t mattr;
	pthread_mutex_t mutex;

	socklen_t socklen;

	memset(cfdFlag, 0, CLIENT_FP_NUM);

	//serverAdd.sin_len=sizeof(struct sockaddr_in);

	bzero(&serverAddr, sizeof(listenFD));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /** INADDR_ANY means let the kernel pick up the address for you when a tcp connection comes.*/

	//inet_pton(AF_INET,"127.0.0.1",&serverAdd.sin_addr);   ---  this function applies to both ipv4 and ipv6

	listenFD = socket(AF_INET, SOCK_STREAM, 0);
	bind(listenFD, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

	listen(listenFD, LISTEN_QUEUE_NUM);

	/**************initialize mutex param*/
	pthread_mutexattr_init(&mattr);
	/*set thread mutex scope---- process private or public*/
	pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE);
	/*check deadlocks or error such like trying to unlock a unlocked mutex*/
	pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK);
	//pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT); /**/
	/*initialize mutex */
	pthread_mutex_init(&mutex, &mattr);
	/*
	 #************************************/

	for (;;) {

		pthread_mutex_lock(&mutex);
		sockNum = getSockNum(cfdFlag);
		pthread_mutex_unlock(&mutex);

		clientFD[sockNum] = accept(listenFD, (struct sockaddr*) &clientAddr,
				&socklen);
		ret = pthread_attr_init(&attr);
		ret = ptchild = pthread_create(&ptchild, &attr, handleConn,
				&(clientFD[sockNum]));

	}
	close(listenFD);
	pthread_mutexattr_destroy(&mattr);
	pthread_mutex_destroy(&mutex);
	exit(0);

}

int getSockNum(int *sockFlag) {

	int i, f;
	int rev = -1;

	loop: for (i = 0; i < CLIENT_FP_NUM; i++) {
		if (sockFlag[i] == 0) {
			rev = i;
			sockFlag[i] = 1;
			break;
		}
	}

	if (rev == -1) {
		sleep(5);
		goto loop;
	} else
		return rev;
}

void handleConn(void *arg) {
	char line[128];
	int *psock = arg;
	for (;;) {
		memset(line, '\0', sizeof(char) * 128);
		if (0 != read(*psock, line, sizeof(char) * 128)) {
			write(*psock, line, sizeof(char) * 128);
		} else {
			printf("Client exited.\n");
			break;
		}
	}
	close(*psock);
	exit(0);
}

//EXBOOL sendFile(char* fname){
//		EXBOOL rev=FALSE;
//
//
//		return rev;
//}
